// 实现这个项目的构建任务
// gulp的入口文件
// 把各个任务作为私有任务 按需要导出 给gulp使用
const { src, dest, series, parallel,watch} = require('gulp');//gulp提供的API
const del = require('del')//del
const browserSync = require('browser-sync')//代码修改后支持自动热更新到浏览器中
const sass = require('gulp-sass')(require('sass'));//转换css插件
// const plugins.babel = require('gulp-babel')//转换es新特性，需要手动按照核心转换模块
// const plugins.swig = require('gulp-swig')//向模板中传数据
// const plugins.imagemin = require('gulp-imagemin')//压缩图片
const loadPlugins = require('gulp-load-plugins')//自动加载插件，不再需要不停的载入插件
const plugins = loadPlugins()//对象，使用到的插件为该对象的属性
const bs = browserSync.create()//创建一个开发服务器，可以实时更新
const data = {//在模板当中使用的数据
    pkg: require('./package.json')
}
const clean = () =>{//del任务 删除
    return del(['dist','temp'])//返回一个promise
}
const style = () =>{//样式的编译任务
    //src指定目标目录，base会把src后面的目录结构保存下来 
    return src('src/assets/styles/*.scss' , {base:'src'})
    .pipe(sass({outputStyle:'expanded'}))//转换过程需要借助插件gulp-sass，函数的结果会返回一个转换流
    .pipe(dest('temp'))//结果目录
    .pipe(bs.reload({stream:true}))
}
const script = () =>{//脚本的编译
    return src('src/assets/scripts/*.js',{base:'src'})//保留原始目录结构
    .pipe(plugins.babel({presets:['@babel/preset-env']}))//转换流插件
    .pipe(dest('temp'))
    .pipe(bs.reload({stream:true}))

}
const page = () =>{//模板文件编译
    return src('src/*.html', {base: 'src'})
    .pipe(plugins.swig({data}))
    .pipe(dest('temp'))
    .pipe(bs.reload({stream:true}))

}
// style和script和page是内容大可需要构建才能使用的，image font文件适合开发过程直接引用，上线之前在构建即可
const image = ()=>{
    return src('src/assets/images/**', {base:'src'})
    .pipe(plugins.imagemin())//压缩图片文件 gulp-imagemin'
    .pipe(dest('dist'))
}
const font = ()=>{//字体压缩处理
    return src('src/assets/fonts/**', {base:'src'})
    .pipe(plugins.imagemin())
    .pipe(dest('dist'))
}
const extra = ()=>{//额外copy的任务
    return src('public/**',{base:'public'})
    .pipe(dest('dist'))
}
const serve = ()=>{
    // watch监听src下的文件, 监听变化后执行的任务--重新生成dist下对应文件，之后会浏览器会更新
    watch('src/assets/styles/**.scss',style)
    watch('src/assets/scripts/*.js', script)//
    watch('src/*.html',page)
    watch([//以下文件修改后 自动重新加载浏览器  不再监听src下图片字体等文件的改变而重新执行对应构建任务，对开发中页面显示没影响还会降低效率
        'src/assets/images/**',
        'src/assets/fonts/**',
        'public/**'
    ], bs.reload)
    bs.init({
        notify:false,//关闭提示
        open:true,//自动打开
        // files:'dist/**',//监听dist下的的文件
        server:{
            baseDir:['temp','src','public'],//会依次查找 例如图片文件可以到src目录下找到// 设置网页的根目录
            routes:{//将该目录下的请求 都指到对应的目录下  先走route 再baseDir
                '/node_modules':'node_modules'
            }
        }
    })
}

const useref = ()=>{//对于js的压缩compile之后再useref保证本次构建有js文件生成
    return src('temp/*.html',{base:'dist'})
    .pipe(plugins.useref({searchPath:['dist','.']}))//useref的使用
    .pipe(plugins.if(/\.js$/,plugins.uglify()))//对新生成的文件进行处理：压缩
    .pipe(plugins.if(/\.css$/,plugins.cleanCss()))//使用插件对不同文件进行压缩
    .pipe(plugins.if(/\.html$/,plugins.htmlmin({
        collapseWhitespace:true,//自动压缩掉空白字符
        minifyCSS:true,//页面中css行内样式的压缩
        minifyJS:true,//页面中script脚本的压缩
    })))//压缩空格
    .pipe(dest('dist'))
}
const compile = parallel(style, script, page)//构建jscsshtml文件
const build = series(clean,parallel(series(compile,useref) ,extra, image, font)) //上线之前执行的任务
const develop = series(compile,serve)//保证serve启动时dist目录存在--开发使用
module.exports = {//导出私有任务
    clean,
    // compile,//src编译任务
    build,//所以文件
    develop,
    // useref,
}

// 
/**补充注释
 * 最新gulp取消了同步模式
 * 组合任务：
 * series   串行执行
 * parallel 同时执行
 * 最终dist目录下打包的内容中可能包含对node_modules文件夹内容的引用，此时node_modules并没有在dist目录下，
 * 在线上环境会出现问题 使用useref插件处理该问题
 * 自动的将注释开始标签和结束标签之间的内容 打包到一个文件当中 并可以进行压缩
 * 在构建过程生成的临时文件先放在temp中 经过useref处理后放入dist中
 */
